﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using DevelopersToolbox.Properties;

namespace DevelopersToolbox {
    public partial class PluginOptions : UserControl {
        private static readonly PluginLoader s_pluginLoader = PluginLoader.Instance;

        public PluginOptions() {
            InitializeComponent();
            ReloadPlugins();
        }

        internal void Initialize(Settings settings) {
            if (settings.SelectedPluginPages == null) {
                return;
            }
            foreach (SelectedPluginPage selectedPluginPage in settings.SelectedPluginPages) {
                IPlugin plugin = s_pluginLoader.GetPlugin(selectedPluginPage.PluginAssemblyQualifiedName);
                if (plugin != null) {
                    IPage page = s_pluginLoader.GetPage(plugin, selectedPluginPage.PageGuid);
                    if (page != null) {
                        SelectedPagesListBoxItem splbi = new SelectedPagesListBoxItem(plugin, page);
                        _selectedPages.Items.Add(splbi);
                    }
                }
            }
        }

        private void ReloadPlugins() {
            _plugins.Items.Clear();
            _pages.Items.Clear();
            foreach (IPlugin plugin in s_pluginLoader.GetPlugins()) {
                _plugins.Items.Add(new PluginListBoxItem(plugin));
            }
        }

        private void _pageMoveUp_Click(object sender, EventArgs e) {
            SelectedPagesListBoxItem splbi = (SelectedPagesListBoxItem)_selectedPages.SelectedItem;
            if (splbi != null) {
                int idx = _selectedPages.SelectedIndex;
                _selectedPages.Items.RemoveAt(idx);
                _selectedPages.Items.Insert(idx - 1, splbi);
                _selectedPages.SelectedIndex = idx - 1;
            }
            RefreshButtonStatus();
        }

        private void _pageMoveDown_Click(object sender, EventArgs e) {
            SelectedPagesListBoxItem splbi = (SelectedPagesListBoxItem)_selectedPages.SelectedItem;
            if (splbi != null) {
                int idx = _selectedPages.SelectedIndex;
                _selectedPages.Items.RemoveAt(idx);
                _selectedPages.Items.Insert(idx + 1, splbi);
                _selectedPages.SelectedIndex = idx + 1;
            }
            RefreshButtonStatus();
        }

        private void _addPage_Click(object sender, EventArgs e) {
            foreach (PagesListBoxItem plbi in _pages.SelectedItems) {
                SelectedPagesListBoxItem splbi = new SelectedPagesListBoxItem(plbi.Plugin, plbi.Page);
                if (!_selectedPages.Items.Contains(splbi)) {
                    _selectedPages.Items.Add(splbi);
                }
            }
            RefreshPages();
            RefreshButtonStatus();
        }

        private void RefreshButtonStatus() {
            PagesListBoxItem plbi = (PagesListBoxItem)_pages.SelectedItem;
            if (plbi != null) {
                SelectedPagesListBoxItem splbi = new SelectedPagesListBoxItem(plbi.Plugin, plbi.Page);
                _addPage.Enabled = !_selectedPages.Items.Contains(splbi);
            } else {
                _addPage.Enabled = false;
            }

            _removePage.Enabled = _selectedPages.SelectedItems.Count > 0;
            _pageMoveUp.Enabled = _selectedPages.SelectedIndex > 0 && _selectedPages.SelectedItems.Count == 1;
            _pageMoveDown.Enabled = _selectedPages.SelectedIndex < _selectedPages.Items.Count - 1 && _selectedPages.SelectedItems.Count == 1;
        }

        private void _removePage_Click(object sender, EventArgs e) {
            List<object> selectedItems = new List<object>();
            foreach (object o in _selectedPages.SelectedItems) {
                selectedItems.Add(o);
            }
            foreach (SelectedPagesListBoxItem splbi in selectedItems) {
                _selectedPages.Items.Remove(splbi);
            }
            RefreshPages();
            RefreshButtonStatus();
        }

        private void _plugins_SelectedIndexChanged(object sender, EventArgs e) {
            RefreshPages();
        }

        private void RefreshPages() {
            _pages.Items.Clear();
            PluginListBoxItem plbi = (PluginListBoxItem)_plugins.SelectedItem;
            if (plbi != null) {
                foreach (IPage page in plbi.Plugin.Pages) {
                    SelectedPagesListBoxItem splbi = new SelectedPagesListBoxItem(plbi.Plugin, page);
                    if (!_selectedPages.Items.Contains(splbi)) {
                        _pages.Items.Add(new PagesListBoxItem(plbi.Plugin, page));
                    }
                }
            }
        }

        private void _pages_SelectedIndexChanged(object sender, EventArgs e) {
            RefreshButtonStatus();
        }


        private void _selectedPages_SelectedIndexChanged(object sender, EventArgs e) {
            RefreshButtonStatus();
        }

        internal void UpdateSettingsWithValues(Settings settings) {
            if (settings.SelectedPluginPages == null) {
                settings.SelectedPluginPages = new SelectedPluginPages();
            }
            settings.SelectedPluginPages.Clear();
            foreach (SelectedPagesListBoxItem splbi in _selectedPages.Items) {
                SelectedPluginPage selectedPluginPage = new SelectedPluginPage {
                    PluginAssemblyQualifiedName = splbi.Plugin.GetType().AssemblyQualifiedName,
                    PageGuid = splbi.Page.Guid
                };
                settings.SelectedPluginPages.Add(selectedPluginPage);
            }
        }

        private class PluginListBoxItem {
            public IPlugin Plugin { get; private set; }

            public PluginListBoxItem(IPlugin plugin) {
                Plugin = plugin;
            }

            public override string ToString() {
                return Plugin.Name;
            }
        }

        private class PagesListBoxItem {
            public IPlugin Plugin { get; private set; }
            public IPage Page { get; private set; }

            public PagesListBoxItem(IPlugin plugin, IPage page) {
                Plugin = plugin;
                Page = page;
            }

            public override string ToString() {
                return Page.Name;
            }
        }

        private class SelectedPagesListBoxItem {
            public IPlugin Plugin { get; private set; }
            public IPage Page { get; private set; }

            public SelectedPagesListBoxItem(IPlugin plugin, IPage page) {
                Plugin = plugin;
                Page = page;
            }

            public override string ToString() {
                return string.Format("{0}: {1}", Plugin.Name, Page.Name);
            }

            public override bool Equals(object obj) {
                if (obj is SelectedPagesListBoxItem) {
                    SelectedPagesListBoxItem splbi = (SelectedPagesListBoxItem)obj;
                    if (splbi.ToString() == ToString()) {
                        return true;
                    }
                }
                return base.Equals(obj);
            }

            public override int GetHashCode() {
                return ToString().GetHashCode();
            }
        }
    }
}
